package net.fonline.apps.pathfinder;

/**
 * The Node is a separate class to the Square, because I wanted map data to be
 * independent of pathfinding data. This class represents one Node in the
 * pathfinding algorithm.
 * @author Scaatis
 */
public class Node {

    //The cost of moving through one square. This could be defined in the
    //associated square as well. Here however, it is the same for all squares
    public static int TRAVERSAL_COST = 10;
    //When traveling diagonally, one travels sqrt(2) times the distance of going
    //horizontally or vertically, this equals about 1.41*10 ~= 14.
    public static int TRAVERSAL_COST_DIAGONAL = 14;
    //Each Node is associated with a Square on the map
    public Square square;
    //To reconstruct a path back from a given Node, each Node has a parent
    public Node parent;

    public Node(Square s, Node p) {
        square = s;
        parent = p;
    }

    /**
     * Get the cost to get from the starting Node to this Node.
     * This is equal to the cost of the parent node plus the cost of this Node.
     * Recursively, we get the cost of the whole path up to this Node.
     * @return The cost to get to this Node.
     */
    public int getParentCost() {
        if (parent == null) {
            return 0;
        } else if (square.isDiagonallyAdjacentTo(parent.square)) {
            return parent.getParentCost() + TRAVERSAL_COST_DIAGONAL;
        } else {
            return parent.getParentCost() + TRAVERSAL_COST;
        }
    }

    /**
     * Estimate the cost to get from this Node to the goal.
     * This is only a rough estimate of course. It is calculated with the Manhattan
     * distance instead of Euclidian distance (look it up) multiplied by the cost
     * to traverse one node. This gets really tricky if you have different traversal
     * costs for different Nodes along the way and might lead to suboptimal paths.
     * But no one said pathfinding would be easy.
     * @param goal
     * @return 
     */
    public int getLocalCost(Square goal) {
        return TRAVERSAL_COST * (Math.abs(square.x - goal.x) + Math.abs(square.y - goal.y));
    }

    /**
     * Also called a Node's F-score. This is the primary criteria for weighing Nodes.
     * It is calculated by adding the ParentCost and the LocalCost.
     * @param goal
     * @return 
     */
    public int getTraversalCost(Square goal) {
        return getParentCost() + getLocalCost(goal);
    }
}